package com.kingdee.eas.hr.affair.app;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.log4j.Logger;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.eas.base.permission.UserInfo;
import com.kingdee.eas.basedata.org.AdminOrgUnitInfo;
import com.kingdee.eas.basedata.org.JobInfo;
import com.kingdee.eas.basedata.org.PositionInfo;
import com.kingdee.eas.basedata.person.Genders;
import com.kingdee.eas.basedata.person.PersonInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.framework.CoreBaseInfo;
import com.kingdee.eas.hr.affair.AsEntryCollection;
import com.kingdee.eas.hr.affair.AsEntryFactory;
import com.kingdee.eas.hr.affair.AsEntryInfo;
import com.kingdee.eas.hr.affair.EmpEnrollBizBillEntryCollection;
import com.kingdee.eas.hr.affair.EmpEnrollBizBillEntryFactory;
import com.kingdee.eas.hr.affair.EmpEnrollBizBillEntryInfo;
import com.kingdee.eas.hr.affair.EmpEnrollBizBillFactory;
import com.kingdee.eas.hr.affair.EmpEnrollBizBillInfo;
import com.kingdee.eas.hr.affair.HRAffairBizBillEntryInfo;
import com.kingdee.eas.hr.base.HRBillStateEnum;
import com.kingdee.eas.hr.emp.PersonPositionCollection;
import com.kingdee.eas.hr.emp.PersonPositionFactory;
import com.kingdee.eas.hr.emp.PersonPositionInfo;
import com.kingdee.eas.hr.org.JobGradeInfo;
import com.kingdee.eas.hr.tools.AdjustSalaryTools;
import com.kingdee.eas.hr.tools.BaseDataTools;
import com.kingdee.eas.hrcus.worklist.EnrollFactory;
import com.kingdee.eas.hrcus.worklist.EnrollInfo;
import com.kingdee.eas.hrcus.worklist.IEnroll;
import com.kingdee.eas.util.app.ContextUtil;
import com.kingdee.shr.compensation.CmpItemFactory;
import com.kingdee.shr.compensation.CmpItemInfo;
import com.kingdee.shr.compensation.FixAdjustSalaryFactory;
import com.kingdee.shr.compensation.IFixAdjustSalary;
import com.kingdee.shr.costbudget.AdjustSalaryBillEntryCollection;
import com.kingdee.shr.costbudget.AdjustSalaryBillEntryInfo;
import com.kingdee.shr.costbudget.AdjustSalaryBillFactory;
import com.kingdee.shr.costbudget.AdjustSalaryBillInfo;
import com.kingdee.shr.costbudget.CmpStandardFactory;
import com.kingdee.shr.costbudget.CmpStandardInfo;
import com.kingdee.shr.costbudget.CmpStdLevelFactory;
import com.kingdee.shr.costbudget.CmpStdLevelInfo;
import com.kingdee.shr.costbudget.CmpStdPointFactory;
import com.kingdee.shr.costbudget.CmpStdPointInfo;
import com.kingdee.shr.costbudget.IAdjustSalaryBill;
import com.kingdee.util.DateTimeUtils;
import com.kingdee.util.NumericExceptionSubItem;
import com.kingdee.util.StringUtils;

/**
 * @Copyright 天津金蝶软件有限公司<br>
 *            Title: EmpEnrollBizBillControllerBeanEx <br>
 *            Description: 入职单扩展类
 * @author yacong_liu Email:yacong_liu@kingdee.com
 * @date 2018-12-21 & 上午09:08:43
 * @since V1.0
 */
public class EmpEnrollBizBillControllerBeanEx extends EmpEnrollBizBillControllerBean {
    private static Logger logger = Logger
            .getLogger("com.kingdee.eas.hr.affair.app.EmpEnrollBizBillControllerBeanEx");

    /**
     * （非 Javadoc）
     * <p>
     * Title: _doWithCommonRelationEffect
     * </p>
     * <p>
     * Description: 提交生效及提交工作流 走此方法
     * </p>
     * 
     * @param ctx
     * @param entry
     * @throws BOSException
     * @throws EASBizException
     * @see com.kingdee.eas.hr.affair.app.EmpEnrollBizBillControllerBean#_doWithCommonRelationEffect(com.kingdee.bos.Context,
     *      com.kingdee.eas.hr.affair.HRAffairBizBillEntryInfo)
     */
    @Override
    protected void _doWithCommonRelationEffect(Context ctx, HRAffairBizBillEntryInfo entry)
            throws BOSException, EASBizException {
        super._doWithCommonRelationEffect(ctx, entry);

        System.out.println("*************************************入职单已触发开始同步定调薪单数据");

        EmpEnrollBizBillEntryInfo empEntry = (EmpEnrollBizBillEntryInfo) entry;
        EmpEnrollBizBillInfo bill = empEntry.getBill();
        saveAdjustSalaryBill(ctx, bill);

        System.out.println("*************************************入职单同步定调薪单数据完成");

        System.out.println("*************************************入职单已触发开始同步入职工作清单数据");

        saveEnrollWorkList(ctx, bill);

        System.out.println("*************************************入职单同步入职工作清单数据完成");

    }

    /**
     * （非 Javadoc）
     * <p>
     * Title: _untiCheckBizBill
     * </p>
     * <p>
     * Description: 反审批
     * </p>
     * 
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws EASBizException
     * @see com.kingdee.eas.hr.affair.app.EmpEnrollBizBillControllerBean#_untiCheckBizBill(com.kingdee.bos.Context,
     *      java.lang.String)
     */
    @Override
    protected void _untiCheckBizBill(Context ctx, String billId) throws BOSException, EASBizException {
        // 撤回同步的定调薪单及薪酬结构记录 撤回的规则:人员 和 生效日期
        EmpEnrollBizBillInfo billInfo = EmpEnrollBizBillFactory.getLocalInstance(ctx)
                .getEmpEnrollBizBillInfo(new ObjectUuidPK(billId));
        // 入职申请日期
        Date applyDate = billInfo.getApplyDate();
        EmpEnrollBizBillEntryCollection entrys = billInfo.getEntrys();
        Iterator entryIterator = entrys.iterator();
        while (entryIterator.hasNext()) {
            EmpEnrollBizBillEntryInfo entry = (EmpEnrollBizBillEntryInfo) entryIterator.next();
            EmpEnrollBizBillEntryInfo entryInfo = EmpEnrollBizBillEntryFactory.getLocalInstance(ctx)
                    .getEmpEnrollBizBillEntryInfo(new ObjectUuidPK(entry.getId().toString()));

            String personId = entryInfo.getPerson().getId().toString();
            logger.info("撤回定调薪单及薪酬结构记录数据：personid= '" + personId + "' applyDate = '" + applyDate + "'");

            revokeAdjustSalaryBill(ctx, personId, applyDate);

        }

        // 撤回已同步的入职工作清单 规则：入职单据编码
        revokeEnrollWorkList(ctx, billInfo.getNumber());

        super._untiCheckBizBill(ctx, billId);

    }

    /**
     * 
     * <p>
     * Title: revokeEnrollWorkList
     * </p>
     * <p>
     * Description: 撤回入职工作清单数据
     * </p>
     * 
     * @param ctx
     * @param billNumber 入职单据编码
     * @throws EASBizException
     * @throws BOSException
     */
    private void revokeEnrollWorkList(Context ctx, String billNumber) throws EASBizException, BOSException {

        if (StringUtils.isEmpty(billNumber)) {
            logger.error("**********************撤回入职工作清单数据参数 billNumber is  null");
            return;
        }

        IEnroll iEnroll = EnrollFactory.getLocalInstance(ctx);
        // 入职单据编码存在则删除，不存在则不操作
        boolean exist = iEnroll.exists(" where enrollBillNum = '" + billNumber + "'");
        if (exist) {

            try {
                iEnroll.delete(" where enrollBillNum = '" + billNumber + "'");

                logger.info("******************************************撤回入职工作清单数据完成");
            } catch (EASBizException e) {
                throw new EASBizException(new NumericExceptionSubItem("03", "删除入职单编码为'" + billNumber
                        + "' 的入职工作清单失败 "));
            } catch (BOSException e) {
                throw new BOSException(e);
            }
        }

    }

    /**
     * 
     * <p>
     * Title: saveEnrollWorkList
     * </p>
     * <p>
     * Description: 同步数据至入职工作清单-未提交状态
     * </p>
     * 
     * @param ctx
     * @param bill
     * @throws BOSException
     * @throws EASBizException
     */
    private void saveEnrollWorkList(Context ctx, EmpEnrollBizBillInfo info) throws EASBizException,
            BOSException {

        if (info == null) {
            logger.error("**************************同步入职工作清单参数：EmpEnrollBizBillInfo is null");
            return;
        }
        // 入职单据编号
        String enrollBillNumber = info.getNumber();
        EmpEnrollBizBillEntryInfo entryInfo = info.getEntrys().get(0);

        PersonInfo person = entryInfo.getPerson();
        String personId = null;
        if (person != null) {
            personId = person.getId().toString();
        }
        PersonInfo personInfo = BaseDataTools.getPersonInfo(ctx, personId);
        // 员工姓名
        String personName = null;
        // 员工编码
        String empNumber = null;
        if (personInfo != null) {
            personName = personInfo.getName();
            empNumber = entryInfo.getEmpNumber();
        }

        // 身份证号
        String cardNo = entryInfo.getIDCardNo();
        // 护照号码
        String passportNo = entryInfo.getPassportNo();
        // 性别
        Genders gender = entryInfo.getGender();
        // 出生日期
        Date birthday = entryInfo.getBirthday();

        PositionInfo position = entryInfo.getPosition();
        String positionId = null;
        if (position != null) {
            positionId = position.getId().toString();
        }
        PositionInfo positionInfo = BaseDataTools.getPositionInfo(ctx, positionId);
        // 职位
        String positionName = null;
        if (positionInfo != null) {
            positionName = positionInfo.getName();
        }

        JobInfo job = entryInfo.getJob();
        String jobId = null;
        if (job != null) {
            jobId = job.getId().toString();
        }
        // 职务
        JobInfo jobInfo = BaseDataTools.getJobInfo(ctx, jobId);
        String jobName = null;
        if (jobInfo != null) {
            jobName = jobInfo.getName();
        }

        AdminOrgUnitInfo adminOrg = entryInfo.getAdminOrg();
        String adminOrgId = null;
        if (adminOrg != null) {
            adminOrgId = adminOrg.getId().toString();
        }
        AdminOrgUnitInfo adminOrgInfo = BaseDataTools.getAdminOrgUnitInfo(ctx, adminOrgId);
        // 所属组织
        String adminOrgName = null;
        if (adminOrgInfo != null) {
            adminOrgName = adminOrgInfo.getName();
        }
        // 入职日期
        Date enrollDate = entryInfo.getEnrollDate();
        // 试用期
        int probation = entryInfo.getProbation();
        // 手机号码
        String telNum = entryInfo.getTelNum();
        // 备注
        String description = entryInfo.getDescription();

        // 构造入职工作清单
        EnrollInfo bill = new EnrollInfo();
        bill.setEnrollBillNum(enrollBillNumber);
        bill.setEmpName(personName);
        bill.setEmpNum(empNumber);
        bill.setIDNum(cardNo);
        bill.setPassportNum(passportNo);
        bill.setGender(gender);
        bill.setBirthDay(birthday);
        bill.setPosition(positionName);
        bill.setPost(jobName);
        bill.setOrgName(adminOrgName);
        bill.setEntryDate(enrollDate);
        bill.setTryMonth(String.valueOf(probation));
        bill.setPhone(telNum);
        bill.setRemark(description);
        bill.setBillState(HRBillStateEnum.SAVED);

        EnrollFactory.getLocalInstance(ctx).save(bill);

    }

    /**
     * 
     * <p>
     * Title: revokeAdjustSalaryBill
     * </p>
     * <p>
     * Description: 撤回定调薪单及薪酬记录数据
     * </p>
     * 
     * @param ctx
     * @param personId 申请人ID
     * @param applyDate 申请日期
     * @throws BOSException
     * @throws EASBizException
     */
    private void revokeAdjustSalaryBill(Context ctx, String personId, Date applyDate) throws BOSException,
            EASBizException {

        IAdjustSalaryBill iAdjustSalaryBill = AdjustSalaryBillFactory.getLocalInstance(ctx);
        try {
            iAdjustSalaryBill.delete(" where person.id = '" + personId + "' and applyDate = {ts'" + applyDate
                    + "'}");

            revokeFixAdjustSalary(ctx, personId, applyDate);

        } catch (EASBizException e) {
            throw new EASBizException(new NumericExceptionSubItem("01", "撤回定调薪单失败！"));
        }

    }

    /**
     * 
     * <p>
     * Title: revokeFixAdjustSalary
     * </p>
     * <p>
     * Description: 撤回定薪单数据（薪酬结构记录）
     * </p>
     * 
     * @param personId 人员Id
     * @param effectDay 生效日期
     * @throws BOSException
     * @throws EASBizException
     */
    private void revokeFixAdjustSalary(Context ctx, String personId, Date effectDay) throws BOSException,
            EASBizException {

        IFixAdjustSalary iFixAdjustSalary = FixAdjustSalaryFactory.getLocalInstance(ctx);
        try {
            iFixAdjustSalary.delete(" where person.id = '" + personId + "' and effectDay = {ts'" + effectDay
                    + "'}");
        } catch (EASBizException e) {
            throw new EASBizException(new NumericExceptionSubItem("02", "撤回定薪单薪酬结构记录失败！"));
        }

    }

    /**
     * 
     * <p>
     * Title: saveAdjustSalaryBill
     * </p>
     * <p>
     * Description: 定调薪单
     * </p>
     * 
     * @param info
     * @throws EASBizException
     * @throws BOSException
     */
    @SuppressWarnings("unchecked")
    private void saveAdjustSalaryBill(Context ctx, EmpEnrollBizBillInfo info) throws EASBizException,
            BOSException {

        EmpEnrollBizBillEntryInfo empEnrollBizBillEntryInfo = info.getEntrys().get(0);
        String id = empEnrollBizBillEntryInfo.getId().toString();
        if (StringUtils.isEmpty(id)) {
            return;
        }
        /*
         * @description 只有入职单入职生效日期是当天时，入职人员才会分配Id。经与PM确认，从业务角度限定只能是当天入职。
         */
        PersonInfo person = empEnrollBizBillEntryInfo.getPerson();
        if (person == null) {
            return;
        }
        String personIdStr = person.getId().toString();

        PersonInfo personInfo = BaseDataTools.getPersonInfo(ctx, personIdStr);
        if (personInfo == null) {
            return;
        }

        CmpStandardInfo entryCmpStandard = (CmpStandardInfo) empEnrollBizBillEntryInfo.get("cmpStandard");
        CmpStandardInfo entryCmpStandardInfo = null;
        if (entryCmpStandard != null) {
            entryCmpStandardInfo = CmpStandardFactory.getLocalInstance(ctx).getCmpStandardInfo(
                    new ObjectUuidPK(entryCmpStandard.getId().toString()));

        }

        /*
         * 定调薪单初始化信息
         */
        Date nowDate = DateTimeUtils.truncateDate(new Date());
        UserInfo currentUserInfo = ContextUtil.getCurrentUserInfo(ctx);
        PersonPositionInfo personPositionInfo = getAdminOrgUnit(ctx, personIdStr);

        // 根据人员获取定调薪单上的人员信息
        AdjustSalaryBillInfo asInfo = new AdjustSalaryBillInfo();
        AsEntryCollection asEntry = info.getAsentry();
        AdjustSalaryBillEntryCollection aseColl = new AdjustSalaryBillEntryCollection();

        Map<String, Object> adjustPersonInfo = AdjustSalaryTools.getPersonOtherInfo(ctx, personIdStr);
        if (adjustPersonInfo != null) {
            AdminOrgUnitInfo nowOrgInfo = null;
            PositionInfo nowPositionInfo = null;
            JobGradeInfo nowJobGradeInfo = null;
            // 现组织
            if (adjustPersonInfo.containsKey("NowOrg")) {
                HashMap<String, String> nowOrg = (HashMap<String, String>) adjustPersonInfo.get("NowOrg");

                nowOrgInfo = BaseDataTools.getAdminOrgUnitInfo(ctx, nowOrg.get("id"));
            }

            // 现职位
            if (adjustPersonInfo.containsKey("NowPosition")) {
                HashMap<String, String> nowPosition = (HashMap<String, String>) adjustPersonInfo
                        .get("NowPosition");

                nowPositionInfo = BaseDataTools.getPositionInfo(ctx, nowPosition.get("id"));
            }

            // 现职等
            if (adjustPersonInfo.containsKey("NowJobGrade")) {
                HashMap<String, String> nowJobGrade = (HashMap<String, String>) adjustPersonInfo
                        .get("NowJobGrade");
                nowJobGradeInfo = BaseDataTools.getJobGradeInfo(ctx, nowJobGrade.get("id"));
            }

            if (personInfo != null) {
                asInfo.setPerson(personInfo);
            }
            if (nowOrgInfo != null) {
                asInfo.setNowOrg(nowOrgInfo);
            }

            if (nowPositionInfo != null) {
                asInfo.setNowPosition(nowPositionInfo);
            }
            if (nowJobGradeInfo != null) {
                asInfo.setNowJobGrade(nowJobGradeInfo);
            }

            // 默认薪酬标准
            if (entryCmpStandardInfo != null) {
                asInfo.setCmpStandard(entryCmpStandardInfo);
            }
            // 制单人
            asInfo.setProposer(currentUserInfo.getPerson());
            // 制单日期
            asInfo.setApplyDate(nowDate);
            // 所属行政组织
            asInfo.setAdminOrg(personPositionInfo.getPersonDep());
            asInfo.setIsMultiEntry(true);

        }

        for (int i = 0; i < asEntry.size(); i++) {
            AsEntryInfo ase = asEntry.get(i);
            AsEntryInfo asEntryInfo = AsEntryFactory.getLocalInstance(ctx).getAsEntryInfo(
                    new ObjectUuidPK(ase.getId().toString()));
            AdjustSalaryBillEntryInfo asbeInfo = new AdjustSalaryBillEntryInfo();

            CmpStandardInfo cmpStandard = asEntryInfo.getCmpStandard();// 薪酬标准
            if (cmpStandard.getId() != null) {
                CmpStandardInfo cmpStandardInfo = CmpStandardFactory.getLocalInstance(ctx)
                        .getCmpStandardInfo(new ObjectUuidPK(cmpStandard.getId().toString()));
                asbeInfo.setCmpStandard(cmpStandardInfo);
            }

            CmpItemInfo cmpItem = asEntryInfo.getCmpItem(); // 薪酬项目
            if (cmpItem.getId() != null) {
                CmpItemInfo cmpItemInfo = CmpItemFactory.getLocalInstance(ctx).getCmpItemInfo(
                        new ObjectUuidPK(cmpItem.getId().toString()));
                asbeInfo.setCmpItem(cmpItemInfo);
            }
            CmpStdLevelInfo cmpLevel = asEntryInfo.getCmpLevel(); // 新薪等
            if (cmpLevel.getId() != null) {
                CmpStdLevelInfo cmpStdLevelInfo = CmpStdLevelFactory.getLocalInstance(ctx)
                        .getCmpStdLevelInfo(new ObjectUuidPK(cmpLevel.getId().toString()));
                asbeInfo.setCmpLevel(cmpStdLevelInfo);

            }
            CmpStdPointInfo stdPoint = asEntryInfo.getStdPoint(); // 新级
            if (stdPoint.getId() != null) {
                CmpStdPointInfo cmpStdPointInfo = CmpStdPointFactory.getLocalInstance(ctx)
                        .getCmpStdPointInfo(new ObjectUuidPK(stdPoint.getId().toString()));

                asbeInfo.setStdPoint(cmpStdPointInfo);

            }

            BigDecimal money = asEntryInfo.getMoney(); // 新值
            Date effectDate = asEntryInfo.getEffectDate();// 生效日期

            asbeInfo.setMoney(money);
            asbeInfo.setEffectDate(effectDate);

            aseColl.add(asbeInfo);

        }
        asInfo.getEntry().addCollection(aseColl);

        // 提交生效_定调薪单（内部自动生成定薪单（薪酬结构记录））
        CoreBaseInfo coreBaseInfo = (CoreBaseInfo) asInfo;
        IAdjustSalaryBill iAdjustSalaryBill = AdjustSalaryBillFactory.getLocalInstance(ctx);
        iAdjustSalaryBill.submitEffect(coreBaseInfo);
    }

    private static PersonPositionInfo getAdminOrgUnit(Context ctx, String personID) {
        if (personID == null) {
            return null;
        }
        PersonPositionInfo personPositionInfo = null;
        StringBuffer oqlb = new StringBuffer();
        oqlb.append("select ");
        oqlb.append("id,");
        oqlb.append("enterDate,");
        oqlb.append("formalDate,");
        oqlb.append("jobGrade.id,");
        oqlb.append("tryoutMonth,");
        oqlb.append("jobGrade.name,");
        oqlb.append("jobLevel.id,");
        oqlb.append("jobLevel.name,");
        oqlb.append("personDep.id,");
        oqlb.append("personDep.name,");
        oqlb.append("personDep.number,");
        oqlb.append("personDep.displayName,");
        oqlb.append("primaryPosition.id,");
        oqlb.append("primaryPosition.name,");
        oqlb.append("primaryPosition.number,");
        oqlb.append("primaryPosition.job.id,");
        oqlb.append("primaryPosition.job.name");
        oqlb.append(" where person.id='");
        oqlb.append(personID);
        oqlb.append("'");
        PersonPositionCollection c = null;
        try {
            c = PersonPositionFactory.getLocalInstance(ctx).getPersonPositionCollection(oqlb.toString());
        } catch (BOSException e) {
            logger.error("getAdminOrgUnit err" + e);
        }
        if ((c != null) && (c.size() > 0)) {
            personPositionInfo = c.get(0);
        }
        return personPositionInfo;
    }

}
